package com.smart.community.commons.base;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smart.community.commons.exception.BusinessException;
import com.smart.community.commons.result.PageResult;
import com.smart.community.commons.result.ResultCode;

import lombok.extern.slf4j.Slf4j;

/**
 * 基础Service实现类
 * 继承MyBatis-Plus的ServiceImpl并实现IBaseService接口
 * 所有业务Service实现类都应该继承此类
 * 提供通用的CRUD操作、分页查询、批量操作、事务管理和缓存功能
 *
 * @author Wu.Liang
 * @version 1.0.0
 * @since 2024-12-19
 */
@Slf4j
public abstract class BaseServiceImpl<M extends BaseMapper<T>, T extends BaseEntity>
        extends ServiceImpl<M, T> implements IBaseService<T> {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    // ========================= 缓存操作 =========================
    protected abstract String getCacheKeyPrefix();

    private String buildCacheKey(Serializable id) {
        return getCacheKeyPrefix() + ":" + id;
    }

    @CacheEvict(value = "entity", key = "'entity:' + #root.target.getCacheKeyPrefix() + ':' + #id")
    public void evictCache(Serializable id) {
        log.debug("清除缓存，ID: {}", id);
    }

    @CacheEvict(value = "entity", allEntries = true)
    public void evictAllCache() {
        log.debug("清除所有缓存");
    }

    public void warmUpCache() {
        log.debug("预热缓存");
        List<T> entities = super.list();
        if (!CollectionUtils.isEmpty(entities)) {
            entities.forEach(entity -> {
                String key = buildCacheKey(entity.getId());
                redisTemplate.opsForValue().set(key, entity, 1, TimeUnit.HOURS);
            });
        }
    }

    // ========================= 条件查询 =========================
    protected QueryWrapper<T> buildQueryWrapper(BaseQuery query) {
        QueryWrapper<T> wrapper = new QueryWrapper<>();
        // 这里只提供基础的查询条件构建，子类可以重写来添加更多条件
        return wrapper;
    }

    // ========================= 分页查询 =========================
    public PageResult<T> pageQuery(BaseQuery query) {
        if (query == null) {
            throw new BusinessException(ResultCode.VALIDATION_FAILED.getCode(), "查询条件不能为空");
        }
        Page<T> page = new Page<>(query.getCurrent(), query.getSize());
        QueryWrapper<T> wrapper = buildQueryWrapper(query);
        IPage<T> result = super.page(page, wrapper);
        return PageResult.of(Math.toIntExact(result.getCurrent()), Math.toIntExact(result.getSize()), result.getTotal(), result.getRecords());
    }

    public PageResult<T> pageQuery(Integer current, Integer size) {
        Page<T> page = new Page<>(current, size);
        IPage<T> result = super.page(page);
        return PageResult.of(Math.toIntExact(result.getCurrent()), Math.toIntExact(result.getSize()), result.getTotal(), result.getRecords());
    }

    public PageResult<T> pageQuery(Integer current, Integer size, BaseQuery query) {
        Page<T> page = new Page<>(current, size);
        QueryWrapper<T> wrapper = buildQueryWrapper(query);
        IPage<T> result = super.page(page, wrapper);
        return PageResult.of(Math.toIntExact(result.getCurrent()), Math.toIntExact(result.getSize()), result.getTotal(), result.getRecords());
    }

    // ========================= 扩展方法实现 =========================
    public List<T> listByQuery(BaseQuery query) {
        QueryWrapper<T> wrapper = buildQueryWrapper(query);
        return super.list(wrapper);
    }

    public long countByQuery(BaseQuery query) {
        QueryWrapper<T> wrapper = buildQueryWrapper(query);
        return super.count(wrapper);
    }

    public boolean existsByQuery(BaseQuery query) {
        QueryWrapper<T> wrapper = buildQueryWrapper(query);
        return super.count(wrapper) > 0;
    }

    public boolean existsById(Serializable id) {
        return super.getById(id) != null;
    }

    public T getOneByQuery(BaseQuery query) {
        QueryWrapper<T> wrapper = buildQueryWrapper(query);
        return super.getOne(wrapper);
    }

    public T getFirstByQuery(BaseQuery query) {
        QueryWrapper<T> wrapper = buildQueryWrapper(query);
        wrapper.last("LIMIT 1");
        return super.getOne(wrapper);
    }

    public T getByIdThrowIfNotFound(Serializable id) {
        T entity = super.getById(id);
        if (entity == null) {
            throw new BusinessException(ResultCode.DATA_NOT_FOUND.getCode(), "数据不存在，ID: " + id);
        }
        return entity;
    }

    public T getOneThrowIfNotFound(BaseQuery query) {
        T entity = getOneByQuery(query);
        if (entity == null) {
            throw new BusinessException(ResultCode.DATA_NOT_FOUND.getCode(), "数据不存在");
        }
        return entity;
    }

    public boolean deleteById(Serializable id) {
        if (id == null) {
            throw new BusinessException(ResultCode.VALIDATION_FAILED.getCode(), "删除的ID不能为空");
        }
        beforeDelete(id);
        boolean result = baseMapper.deleteById(id) > 0;
        afterDelete(id);
        return result;
    }

    public boolean deleteByIds(Collection<? extends Serializable> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            throw new BusinessException(ResultCode.VALIDATION_FAILED.getCode(), "删除的ID不能为空");
        }
        log.debug("批量物理删除实体，IDs: {}", ids);
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    public boolean deleteByQuery(BaseQuery query) {
        if (query == null) {
            throw new BusinessException(ResultCode.VALIDATION_FAILED.getCode(), "删除条件不能为空");
        }
        QueryWrapper<T> wrapper = buildQueryWrapper(query);
        return baseMapper.delete(wrapper) > 0;
    }

    public boolean removeByQuery(BaseQuery query) {
        QueryWrapper<T> wrapper = buildQueryWrapper(query);
        return super.remove(wrapper);
    }

    // ========================= 钩子方法 =========================
    protected void beforeSave(T entity) {
        log.debug("保存前处理: {}", entity);
    }

    protected void afterSave(T entity) {
        log.debug("保存后处理: {}", entity);
    }

    protected void beforeUpdate(T entity) {
        log.debug("更新前处理: {}", entity);
    }

    protected void afterUpdate(T entity) {
        log.debug("更新后处理: {}", entity);
    }

    protected void beforeDelete(Serializable id) {
        log.debug("删除前处理，ID: {}", id);
    }

    protected void afterDelete(Serializable id) {
        log.debug("删除后处理，ID: {}", id);
    }

    protected void validateEntity(T entity) {
        if (entity == null) {
            throw new BusinessException(ResultCode.VALIDATION_FAILED.getCode(), "实体不能为空");
        }
        // 子类可以重写此方法来添加更多验证逻辑
    }
}
